package com.rzgeo.rzmaplib.comp;

import android.content.Context;
import android.graphics.Color;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.SparseBooleanArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.FrameLayout;
import android.widget.ListView;
import android.widget.TextView;

import com.esri.arcgisruntime.concurrent.ListenableFuture;
import com.esri.arcgisruntime.data.Feature;
import com.esri.arcgisruntime.data.FeatureQueryResult;
import com.esri.arcgisruntime.data.FeatureTable;
import com.esri.arcgisruntime.data.Field;
import com.esri.arcgisruntime.data.QueryParameters;
import com.esri.arcgisruntime.geometry.Geometry;
import com.esri.arcgisruntime.geometry.GeometryEngine;
import com.esri.arcgisruntime.geometry.Point;
import com.esri.arcgisruntime.layers.FeatureLayer;
import com.esri.arcgisruntime.layers.Layer;
import com.esri.arcgisruntime.loadable.LoadStatus;
import com.esri.arcgisruntime.mapping.GeoElement;
import com.esri.arcgisruntime.mapping.view.Graphic;
import com.esri.arcgisruntime.mapping.view.GraphicsOverlay;
import com.esri.arcgisruntime.symbology.SimpleMarkerSymbol;
import com.esri.arcgisruntime.symbology.SimpleRenderer;
import com.esri.arcgisruntime.symbology.Symbol;
import com.rzgeo.rzmaplib.R;
import com.rzgeo.rzmaplib.comp.geoview.IRmlGeoViewHolder;
import com.rzgeo.rzmaplib.util.RmlUtil;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;

/**
 * Created by zhanghang on 2018/2/5.
 */

public class RmlMarkList extends FrameLayout implements AdapterView.OnItemClickListener {
    private ListView lvMarkers;
    private View btnAdd;
    private View btnMinus;
    private View btnClear;
    private FeatureLayer _fl;
    private MarkAdapt _adapt;
    private View tbMain;
    private View tbEdit;
    private RmlPanel rpTools;
    private TextView editTitle;
    private IRmlGeoViewHolder _geoViewHolder;
    private GraphicsOverlay _gl;
    private Symbol _tempSymbol;
    private Symbol _LayerSymbol;

    public RmlMarkList(Context context) {
        super(context);
        initUI(context);
    }

    public RmlMarkList(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        initUI(context);
    }

    public RmlMarkList(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initUI(context);
    }

    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        MarkBean mark= (MarkBean) _adapt.getItem(position);
        if(mark!=null){
            _geoViewHolder.setViewPoint(mark.geometry.getExtent().getCenter());
        }
    }

    private void initUI(Context context) {
        View subView = LayoutInflater.from(context).inflate(R.layout.comp_marker_list, null);
        subView.setLayoutParams(
                new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
        this.addView(subView);

        _gl=new GraphicsOverlay();
//        _tempSymbol=new SimpleMarkerSceneSymbol(
//                SimpleMarkerSceneSymbol.Style.DIAMOND,
//                Color.RED,
//                24,
//                18,
//                1,
//                SceneSymbol.AnchorPosition.BOTTOM
//        );

        _tempSymbol=new SimpleMarkerSymbol(
                SimpleMarkerSymbol.Style.CROSS,
                Color.RED,
                16
        );
        _LayerSymbol=new SimpleMarkerSymbol(
                SimpleMarkerSymbol.Style.TRIANGLE,
                Color.GREEN,
                16
        );
    }

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();

        rpTools=findViewById(R.id.rp_tools);
        btnAdd=findViewById(R.id.btn_add);
        btnMinus=findViewById(R.id.btn_minus);
        btnClear=findViewById(R.id.btn_clear);

        btnAdd.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                rpTools.setOnSelect(tbEdit.getId());
                _geoViewHolder.onMapTouch(new IRmlGeoViewHolder.OnTouchListener(){

                    @Override
                    public void onTouch(Point mp, android.graphics.Point sp, List<GeoElement> elements) {
                        try {
                            mp= (Point) GeometryEngine.project(mp,_geoViewHolder.getGeoView().getSpatialReference());
                            Graphic g=new Graphic(mp,_tempSymbol);
                            _gl.getGraphics().clear();
                            _gl.getGraphics().add(g);
                        }catch (Exception e){
                            RmlUtil.Log.Err(e);
                        }
                    }

                    @Override
                    public Layer wantLayer() {
                        return _fl;
                    }

                    @Override
                    public double getTolerance() {
                        return 20;
                    }

                    @Override
                    public int getMaxReturn() {
                        return 2;
                    }
                });
            }
        });

        btnMinus.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                int pos = lvMarkers.getCheckedItemPosition();
                if(pos>-1){
                    Feature f = ((MarkBean) _adapt.getItem(pos))._f;
                    FeatureTable ft = _fl.getFeatureTable();
                    if(f!=null&&ft.isEditable()){
                        final ListenableFuture<Void> dft = ft.deleteFeatureAsync(f);
                        dft.addDoneListener(new Runnable() {
                            @Override
                            public void run() {
                                try {
                                    dft.get();
                                } catch (InterruptedException|ExecutionException e) {
                                    RmlUtil.Log.Err(e);
                                } finally {
                                    reloadData();
                                }
                            }
                        });
                    }
                }
            }
        });

        btnClear.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {

            }
        });

        lvMarkers=findViewById(R.id.lv_markers);
        lvMarkers.setChoiceMode(AbsListView.CHOICE_MODE_SINGLE);
        lvMarkers.setOnItemClickListener(this);

        tbMain=findViewById(R.id.tb_main);
        tbEdit=findViewById(R.id.tb_edit);


        editTitle=findViewById(R.id.txv_title);
        editTitle.setText("点击地图绘制,然后确认");

        findViewById(R.id.btn_cancel).setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                _gl.getGraphics().clear();
                rpTools.setOnSelect(tbMain.getId());
            }
        });

        findViewById(R.id.btn_ok).setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                if(_gl.getGraphics().size()>0)
                {
                    RmlUtil.Dialog.InputString(getContext(), "", new RmlUtil.Dialog.OnInputText() {
                        @Override
                        public void onResult(String content) {
                            rpTools.setOnSelect(tbMain.getId());
                            Graphic g = _gl.getGraphics().get(0);
                            _gl.getGraphics().clear();

                            FeatureTable ft = _fl.getFeatureTable();
                            if(ft.isEditable()&& ft.canAdd()){

                                Geometry geo = GeometryEngine.project(g.getGeometry(), ft.getSpatialReference());
                                geo=RmlUtil.Geo.fitZValue(geo,ft.hasZ());
                                Feature f = ft.createFeature(
                                        MarkBean.toAttrs(content),geo);
                                final ListenableFuture<Void> lf = ft.addFeatureAsync(f);
                                lf.addDoneListener(new Runnable() {
                                    @Override
                                    public void run() {
                                        try {
                                            Void lr = lf.get();
                                        } catch (InterruptedException|ExecutionException e) {
                                            e.printStackTrace();
                                        }finally {
                                            reloadData();
                                        }
                                    }
                                });
                            }else{
                                RmlUtil.Tip.Alert(getContext(),"shp文件无法编辑");
                            }
                        }

                        @Override
                        public void onCancel() {

                        }
                    });
                }
            }
        });

    }

    public void setup(IRmlGeoViewHolder geoViewHolder, FeatureLayer featureLayer){
        _fl = featureLayer;
        _fl.setRenderer(new SimpleRenderer(_LayerSymbol));
        _geoViewHolder=geoViewHolder;
        _geoViewHolder.getGraphicsOverlays().add(_gl);
        if(_fl.getFeatureTable().getLoadStatus()== LoadStatus.LOADED){
            loadDataFromTable();
        }else{
            _fl.getFeatureTable().addDoneLoadingListener(new Runnable() {
                @Override
                public void run() {
                    loadDataFromTable();
                }
            });
        }
    }

    private void loadDataFromTable() {
        MarkBean.initField(_fl.getFeatureTable());

        lvMarkers.setChoiceMode(AbsListView.CHOICE_MODE_SINGLE);

        _adapt=new MarkAdapt(getContext());
        lvMarkers.setAdapter(_adapt);
        reloadData();
    }

    private void reloadData() {
        QueryParameters qp=new QueryParameters();
        final ListenableFuture<FeatureQueryResult> fq = _fl.getFeatureTable().queryFeaturesAsync(qp);
        fq.addDoneListener(new Runnable() {
            @Override
            public void run() {
                try {
                    FeatureQueryResult fr = fq.get();
                    ArrayList<MarkBean>markBeans=new ArrayList<>();
                    Iterator<Feature> iterator = fr.iterator();
                    while (iterator.hasNext()){
                        Feature f = iterator.next();
                        markBeans.add(new MarkBean(f));
                    }
                    _adapt.setData(markBeans);
                } catch (Exception e) {
                    RmlUtil.Log.Err(e);
                }

            }
        });
    }

    public static class MarkBean{
        public static Field FOid;

        public static Field FMsg;
        public static Field FEditTim;
        public static Field FCreator;
        public static Field FCreateTim;
        public final Feature _f;
        public long oid;
        public String Msg;
        private Geometry geometry;

        public MarkBean(Feature f) {
            _f=f;
            geometry=f.getGeometry();
            oid= RmlUtil.Convert.toLong( f.getAttributes().get(FOid.getName()));
            Msg= RmlUtil.Convert.toString( f.getAttributes().get(FMsg.getName()));
        }



        public static void initField(FeatureTable table) {
            if(MarkBean.FOid ==null){
                for (Field f:table.getFields()){
                    if(f.getFieldType()== Field.Type.OID){
                        MarkBean.FOid =f;
                    }
                    else if("Msg".equalsIgnoreCase(f.getName())){
                        MarkBean.FMsg =f;
                    }
                    else if("EditTim".equalsIgnoreCase(f.getName())){
                        MarkBean.FEditTim =f;
                    }
                    else if("Creator".equalsIgnoreCase(f.getName())){
                        MarkBean.FCreator =f;
                    }
                    else if("CreateTim".equalsIgnoreCase(f.getName())){
                        MarkBean.FCreateTim =f;
                    }
                }
            }
        }

        public static void initFeature(Feature f, Graphic g, String content) {

            f.setGeometry(g.getGeometry());
            f.getAttributes().put(FMsg.getName(),content);
            f.getAttributes().put(FEditTim.getName(), RmlUtil.Convert.toDateString(new Date()));
            f.getAttributes().put(FCreateTim.getName(),RmlUtil.Convert.toDateString(new Date()));
        }

        public static Map<String, Object> toAttrs(String content) {
            java.util.Map<String, Object> attrs = new HashMap<>();
            attrs.put(FMsg.getName(),content);
//            attrs.put(FEditTim.getName(), RmlUtil.Convert.toDateString(new Date()));
//            attrs.put(FCreateTim.getName(),RmlUtil.Convert.toDateString(new Date()));
            attrs.put(FCreator.getName(),"");
            return attrs;
        }
    }

    private class MarkAdapt extends BaseAdapter {

        private ArrayList<MarkBean>_markBeans;
        private LayoutInflater _inflater;

        public MarkAdapt(Context context) {
            _inflater= LayoutInflater.from(context);
            _markBeans=null;
        }

        @Override
        public int getCount() {
            if(_markBeans==null)
                return 0;
            return _markBeans.size();
        }

        @Override
        public Object getItem(int position) {
            return _markBeans.get(position);
        }

        @Override
        public long getItemId(int position) {
            return _markBeans.get(position).oid;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            MarkViewHolder holder;
            if (convertView == null) {
                convertView = _inflater.inflate(R.layout.comp_marker_list_item, null);
                holder = new MarkViewHolder(convertView);
                convertView.setTag(holder);
            } else {
                holder = (MarkViewHolder) convertView.getTag();
            }

            holder.setData(_markBeans.get(position),position);
            return convertView;
        }

        public void setData(ArrayList<MarkBean> markBeans){
            _markBeans=markBeans;
            notifyDataSetChanged();
        }

        private class MarkViewHolder implements OnClickListener {
            private final View btnEdit;
            private final View btnLocate;
            private final TextView txvMsg;
            private MarkBean _markBean;

            public MarkViewHolder(View convertView) {
                txvMsg = convertView.findViewById(R.id.txv_msg );
                btnLocate = convertView.findViewById(R.id.btn_locate  );
                btnEdit = convertView.findViewById(R.id.btn_edit);

                btnLocate.setOnClickListener(this);
                btnEdit.setOnClickListener(this);
            }

            public void setData(MarkBean markBean, int position) {
                _markBean=markBean;
                txvMsg.setText(markBean.Msg);

            }

            @Override
            public void onClick(View v) {
                if(_markBean!=null&&_geoViewHolder!=null){
                    if(v.getId()==btnLocate.getId()){
                        _geoViewHolder.setViewPoint((Point) _markBean.geometry);
                    }else if(v.getId()==btnEdit.getId()){
                        RmlUtil.Dialog.InputString(getContext(), _markBean.Msg, new RmlUtil.Dialog.OnInputText() {
                            @Override
                            public void onResult(String content) {
                                if(_markBean.Msg!=null&&(!_markBean.Msg.equalsIgnoreCase(content))){
                                    FeatureTable ft = _fl.getFeatureTable();

                                    if(ft.isEditable()&& ft.canAdd()) {

                                        _markBean._f.getAttributes().put(MarkBean.FMsg.getName(),content);
                                        final ListenableFuture<Void> uft = ft.updateFeatureAsync(_markBean._f);
                                        uft.addDoneListener(new Runnable() {
                                            @Override
                                            public void run() {
                                                try {
                                                    uft.get();
                                                    reloadData();
                                                } catch (InterruptedException|ExecutionException e) {
                                                    RmlUtil.Log.Err(e);
                                                }
                                            }
                                        });
                                    }
                                }
                            }

                            @Override
                            public void onCancel() {

                            }
                        });
                    }
                }
            }
        }
    }

}
